import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError
} from 'axios'
// import {
//   showFullScreenLoading,
//   tryHideFullScreenLoading
// } from '@/hooks/serviceLoading'
import { useLoading } from '@/hooks/loading'
import { NO_TOKEN_API, TOKEN_PREFIX } from './constants'
import { checkStatus } from './checkStatus'
// import { AxiosCanceler } from './axiosCancel'
import { useAppStore } from '@/store'
import { ContentType, ResCode } from '@/enums'
import { ElMessage } from 'element-plus'

import router from '@/router'

// const axiosCancel = new AxiosCanceler()

const { serverLoading, closeLoading } = useLoading()

const config = {
  baseURL: '/api',
  timeout: ResCode.TIMEOUT as number,
  // 跨域时候允许携带凭证
  withCredentials: true
}

class Service {
  instance: AxiosInstance

  public constructor(config: AxiosRequestConfig) {
    // 实例化axios
    this.instance = axios.create(config)

    /**
     * 请求拦截
     */
    this.instance.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        const appStore = useAppStore()

        /** 将请求添加到 pending 中 */
        // axiosCancel.addPending(config)

        /** 设置全局 loading */
        serverLoading()

        /** 添加请求 token */
        const token = appStore.token
        const headers = !NO_TOKEN_API.includes(config.url!)
          ? {
              'Content-Type': ContentType.JSON,
              Authorization: `${TOKEN_PREFIX}${token}`
            }
          : null
        return {
          ...config,
          headers
        }
      },
      (err: AxiosError) => {
        closeLoading()
        return Promise.reject(err)
      }
    )

    /**
     * 响应拦截
     */
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        const appStore = useAppStore()
        // console.log(response)
        const { data, config } = response
        // console.log(data, config)
        /** 移除本次请求 */
        // axiosCancel.removePending(config)

        /** 关闭加载动画 */
        closeLoading()

        if (data.code === ResCode.OVERDUE) {
          ElMessage.error(data.msg)
          appStore.logout()
          router.push({
            path: '/login'
          })
        } else if (data.code === ResCode.ERROR) {
          if (config.url !== 'login') {
            ElMessage.error(data.msg)
          }
        } else if (data.code !== ResCode.SUCCESS) {
          ElMessage.error(data.msg)
        } else {
          return data
        }

        // /** 登录失效 401 */
        // if (data.code === ResCode.OVERDUE) {
        //   ElMessage.error(data.msg)
        //   appStore.logout()
        //   router.push({
        //     path: '/login'
        //   })
        //   return
        // }

        // /** 全局错误信息拦截 */
        // if (data.code !== 200) {
        //   ElMessage.error(data.msg)
        //   return Promise.reject(data)
        // }

        // return data
      },
      (err: AxiosError) => {
        closeLoading()
        console.log(err)
        const { response } = err
        if (response) return checkStatus(response.status)

        /** 服务器结果都没有返回(可能服务器错误可能客户端断网)，断网处理:可以跳转到断网页面 */
        if (!window.navigator.onLine)
          return router.replace({ path: '/noFound' })

        return Promise.reject(err)
      }
    )
  }

  // request<T>(config: AxiosRequestConfig): Promise<T> {
  //   return new Promise((resolve, reject) => {
  //     this.instance
  //       .request<any, T>(config)
  //       .then((res) => {
  //         resolve(res)
  //       })
  //       .catch((err) => {
  //         reject(err)
  //       })
  //   })
  // }

  /** 常用请求方法封装 */
  get<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.instance.get(url, { params, ..._object })
  }
  post<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.instance.post(url, params, _object)
  }
  put<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.instance.put(url, params, _object)
  }
  delete<T>(url: string, params?: any, _object = {}): Promise<T> {
    return this.instance.delete(url, { params, ..._object })
  }

  /** 常用请求方法封装 */
  // get<T>(config: AxiosRequestConfig): Promise<T> {
  //   return this.request<T>({ ...config, method: 'GET' })
  // }
  // post<T>(config: AxiosRequestConfig): Promise<T> {
  //   return this.request<T>({ ...config, method: 'POST' })
  // }
  // put<T>(config: AxiosRequestConfig): Promise<T> {
  //   return this.request<T>({ ...config, method: 'PUT' })
  // }
  // delete<T>(config: AxiosRequestConfig): Promise<T> {
  //   return this.request<T>({ ...config, method: 'DELETE' })
  // }
}

export default new Service(config)
